package service

import (
	"context"
	"errors"
	"gitee.com/jinmingzhi/cdce-service/internal/model"
	"gitee.com/jinmingzhi/cdce-service/internal/repository"
	"gitee.com/jinmingzhi/cdce-service/pkg/errs"
	"go.uber.org/zap"
)

type User interface {
	FindUser(ctx context.Context, uid uint32) (*model.User, *model.UserDetail, error)
	FindUserByUid(ctx context.Context, uid uint32) (*model.User, error)
	SetPasswd(ctx context.Context, uid uint32, old_passwd, new_passwd string) error
}

type userImpl struct {
	UserRepo repository.User
}

func NewUser(user_repo repository.User) *userImpl {
	return &userImpl{
		UserRepo: user_repo,
	}
}

func (u *userImpl) Auth(principal, credential string) (uid uint32, err error) {
	user, err := u.UserRepo.FindUser(context.Background(), principal)
	if err != nil {
		return 0, err
	}
	if !user.ComParePasswd(credential) {
		return 0, errors.New("user and passwd failed")
	}
	return user.ID, nil
}

func (u *userImpl) FindUser(ctx context.Context, uid uint32) (*model.User, *model.UserDetail, error) {
	user, err := u.UserRepo.FindUserByUid(ctx, uid)
	if err != nil {
		log.Error("UserRepo.FindUserByUid", zap.Uint32("uid", uid), zap.Error(err))
		return nil, nil, err
	}
	userDetail, err := u.UserRepo.FindUserDetail(ctx, uid)
	if err != nil {
		log.Error("UserRepo.FindUserDetail", zap.Uint32("uid", uid), zap.Error(err))
		return nil, nil, err
	}
	return user, userDetail, nil
}

func (u *userImpl) FindUserByUid(ctx context.Context, uid uint32) (*model.User, error) {
	user, err := u.UserRepo.FindUserByUid(ctx, uid)
	if err != nil {
		return nil, err
	}
	return user, nil
}

func (u *userImpl) SetPasswd(ctx context.Context, uid uint32, old_passwd, new_passwd string) error {
	user, err := u.UserRepo.FindUserByUid(ctx, uid)
	if err != nil {
		return err
	}
	if !user.ComParePasswd(old_passwd) {
		return errs.ErrWrongPasswd
	}

	err = u.UserRepo.SetPasswd(ctx, uid, model.EncrypPasswd(new_passwd))
	if err != nil {
		log.Error("setpasswd failed", zap.Int("uid", int(uid)), zap.Error(err))
		return errors.New("modify passwd failed")
	}
	return nil
}
